Security News
Input Validation Vulnerabilities Dominate MITRE's 2024 CWE Top 25 List
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
reactive-property
Advanced tools
This tiny library abstracts the getter-setter pattern described in Towards Reusable Charts (by Mike Bostock, 2012) and adds the ability to react to changes in state.
Install the library by running this command.
npm install reactive-property
Require it in your code like this.
var ReactiveProperty = require("reactive-property");
If you're not using NPM, you can require the script in your HTML like this.
<script src="//curran.github.io/reactive-property/reactive-property-v0.6.0.js"></script>
Or, you can use the minified version (1.5K).
<script src="//curran.github.io/reactive-property/reactive-property-v0.6.0.min.js"></script>
Create your first property.
var a = ReactiveProperty();
Set its value.
a(5);
Get its value.
a();
Listen for changes.
a.on(function(value){
console.log("The value of 'a' changed to " + value);
});
Cancel your subscription.
function listener(){
console.log("'a' changed!");
}
a.on(listener);
a.off(listener);
a(5); // The listener is NOT called.
For convenenience, the listener function is returned from the call to on
, so the following would also work.
var listener = a.on(function (){
console.log("'a' changed!");
});
a.off(listener);
a(5); // The listener is NOT called.
Set up method chaining by using a context object.
var my = {
x: ReactiveProperty(5),
y: ReactiveProperty(10),
z: ReactiveProperty(15)
};
my.x(50)
.y(100)
.z(150);
For more detailed example code, have a look at the tests..
After many attempts at building "frameworks" for data visualization (ModelJS, Chiasm), I have learned that abstractions come at a cost. Much to my dismay, I found that when I wanted to apply Chiasm to a particular project, the abstractions had too much surface area and stood in the way of customization. I found myself starting again from raw D3 examples to get projects done, and noticed that as a project grows in complexity organically, the most common need is to listen for changes in state.
This library is my attempt to create a "micro-framework" that eliminates the getter-setter boilerplate code and provides the ability to listen for changes in state. It is intentionally minimal, and no other features are provided. This is to minimize the surface area of this library, and make it appealing for others to adopt as a utility. It is intended for use with D3-based projects, as it helps you generate APIs that follow the D3 convention of chainable getter-setters, but it can be used with other libraries too.
This library is "complete" and fully functional as-is. Aside from bugs or edge cases that come up, no new features will be added to this library. This library is designed to be the foundation of larger systems, and additional functionality should arise by composing this library with other code.
This library is essentially a state container. You will experience totally predictable behavior if you set property values to immutable values. For example, if you want a property to represent a list of things, it may be tempting to do this:
var myList = ReactiveProperty(["a"]);
myList.on(function (value){ console.log("Updated"); });
myList().push("b"); // Listener does not get invoked.
However, in this case, the listener does not get invoked when you push the element onto the array. The same is true for objects.
var myObject = ReactiveProperty({ x: 5 });
myObject.on(function (value){ console.log("Updated"); });
myObject().y = 10; // Listener does not get invoked.
In order to trigger the listener, you must invoke the setter, like this:
var myList = ReactiveProperty(["a"]);
myList.on(function (value){ console.log("Updated"); });
myList(["a", "b"]); // Listener does get invoked.
However, let's say you want to use push
, how could that work?
var myList = ReactiveProperty(["a"]);
myList.on(function (value){ console.log("Updated"); });
myList().push("b"); // Object mutated, listener not invoked.
myList(myList()); // Listener does get invoked.
In the case of objects:
var myObject = ReactiveProperty({ x: 5 });
myObject.on(function (value){ console.log("Updated"); });
myObject().y = 10; // Object mutated, listener not invoked.
myObject(myObject()); // This triggers the listener, but is ugly.
The above solution does work, but it's actually mutating the value, then passing it into the setter. This is not ideal. In situations like this, you're better off using immutable types such as those provided in Immutable.js for complex value types. Here's what that would look like for arrays (Lists):
var myList = ReactiveProperty(Immutable.List(["a"]););
myList.on(function (value){ console.log("Updated"); });
myList(myList().push("b")); // Sets the new value, invokes the listener.
Here's what using immutable types would look like for arrays (Maps):
var myMap = ReactiveProperty(Immutable.Map({ x: 5 }););
myMap.on(function (value){ console.log("Updated"); });
myMap(myMap().set("y", 10)); // Sets the new value, invokes the listener.
This is a good solution, and yields predictable behavior that is easy to reason about.
I hope you enjoy and benefit from this project!
FAQs
A small library for getter-setter functions that react to changes.
The npm package reactive-property receives a total of 1 weekly downloads. As such, reactive-property popularity was classified as not popular.
We found that reactive-property demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.
Research
Security News
A threat actor's playbook for exploiting the npm ecosystem was exposed on the dark web, detailing how to build a blockchain-powered botnet.